var s = document.createElement("script");

/**
 * Modified version of hammerjs' touch emulator - github.com/hammerjs/touchemulator
 */
s.textContent = "(" + (function(window, document, undefined) {
	var isMultiTouch = false;
	var multiTouchStartPos;
	var eventTarget;

	// polyfills
	if(!document.createTouch) {
		document.createTouch = function(view, target, identifier, pageX, pageY, screenX, screenY, clientX, clientY) {
			// auto set
			if(clientX === undefined || clientY === undefined) {
				clientX = pageX - window.pageXOffset;
				clientY = pageY - window.pageYOffset;
			}

			return new Touch(target, identifier, {
				pageX: pageX,
				pageY: pageY,
				screenX: screenX,
				screenY: screenY,
				clientX: clientX,
				clientY: clientY
			});
		};
	}

	if(!document.createTouchList) {
		document.createTouchList = function() {
			var touchList = new TouchList();
			for (var i = 0; i < arguments.length; i++) {
				touchList[i] = arguments[i];
			}
			touchList.length = arguments.length;
			return touchList;
		};
	}

	/**
	 * create an touch point
	 * @constructor
	 * @param target
	 * @param identifier
	 * @param pos
	 * @param deltaX
	 * @param deltaY
	 * @returns {Object} touchPoint
	 */
	function Touch(target, identifier, pos, deltaX, deltaY) {
		deltaX = deltaX || 0;
		deltaY = deltaY || 0;

		this.identifier = identifier;
		this.target = target;
		this.clientX = pos.clientX + deltaX;
		this.clientY = pos.clientY + deltaY;
		this.screenX = pos.screenX + deltaX;
		this.screenY = pos.screenY + deltaY;
		this.pageX = pos.pageX + deltaX;
		this.pageY = pos.pageY + deltaY;
	}

	/**
	 * create empty touchlist with the methods
	 * @constructor
	 * @returns touchList
	 */
	function TouchList() {
		var touchList = [];

		touchList.item = function(index) {
			return this[index] || null;
		};

		// specified by Mozilla
		touchList.identifiedTouch = function(id) {
			return this[id + 1] || null;
		};

		return touchList;
	}


	/**
	 * Simple trick to fake touch event support
	 * this is enough for most libraries like Modernizr and Hammer
	 */
	function fakeTouchSupport() {
		var objs = [window, document.documentElement];
		var props = ['ontouchstart', 'ontouchmove', 'ontouchcancel', 'ontouchend'];

		for(var o=0; o<objs.length; o++) {
			for(var p=0; p<props.length; p++) {
				if(objs[o] && objs[o][props[p]] === undefined) {
					objs[o][props[p]] = null;
				}
			}
		}
	}

	/**
	 * only trigger touches when the left mousebutton has been pressed
	 * @param touchType
	 * @returns {Function}
	 */
	function onMouse(touchType) {
		return function(ev) {
			if (ev.which !== 1) {
				return;
			}

			// The EventTarget on which the touch point started when it was first placed on the surface,
			// even if the touch point has since moved outside the interactive area of that element.
			// also, when the target doesnt exist anymore, we update it
			if (ev.type === 'mousedown' || !eventTarget || (eventTarget && !eventTarget.dispatchEvent)) {
				eventTarget = ev.target;
			}

			// shiftKey has been lost, so trigger a touchend
			if (isMultiTouch && !ev.shiftKey) {
				triggerTouch('touchend', ev);
				isMultiTouch = false;
			}

			triggerTouch(touchType, ev);

			// we're entering the multi-touch mode!
			if (!isMultiTouch && ev.shiftKey) {
				isMultiTouch = true;
				multiTouchStartPos = {
					pageX: ev.pageX,
					pageY: ev.pageY,
					clientX: ev.clientX,
					clientY: ev.clientY,
					screenX: ev.screenX,
					screenY: ev.screenY
				};
				triggerTouch('touchstart', ev);
			}

			// reset
			if (ev.type === 'mouseup') {
				multiTouchStartPos = null;
				isMultiTouch = false;
				eventTarget = null;
			}
		};
	}

	/**
	 * trigger a touch event
	 * @param eventName
	 * @param mouseEv
	 */
	function triggerTouch(eventName, mouseEv) {
		var touchEvent = document.createEvent('Event');
		touchEvent.initEvent(eventName, true, true);

		touchEvent.altKey = mouseEv.altKey;
		touchEvent.ctrlKey = mouseEv.ctrlKey;
		touchEvent.metaKey = mouseEv.metaKey;
		touchEvent.shiftKey = mouseEv.shiftKey;

		touchEvent.touches = getActiveTouches(mouseEv, eventName);
		touchEvent.targetTouches = getActiveTouches(mouseEv, eventName);
		touchEvent.changedTouches = getChangedTouches(mouseEv, eventName);

		eventTarget.dispatchEvent(touchEvent);
	}

	/**
	 * create a touchList based on the mouse event
	 * @param mouseEv
	 * @returns {TouchList}
	 */
	function createTouchList(mouseEv) {
		var touchList = new TouchList();

		if (isMultiTouch) {
			var f = TouchEmulator.multiTouchOffset;
			var deltaX = multiTouchStartPos.pageX - mouseEv.pageX;
			var deltaY = multiTouchStartPos.pageY - mouseEv.pageY;

			touchList.push(new Touch(eventTarget, 1, multiTouchStartPos, (deltaX*-1) - f, (deltaY*-1) + f));
			touchList.push(new Touch(eventTarget, 2, multiTouchStartPos, deltaX+f, deltaY-f));
		} else {
			touchList.push(new Touch(eventTarget, 1, mouseEv, 0, 0));
		}

		return touchList;
	}

	/**
	 * receive all active touches
	 * @param mouseEv
	 * @returns {TouchList}
	 */
	function getActiveTouches(mouseEv, eventName) {
		// empty list
		if (mouseEv.type === 'mouseup') {
			return new TouchList();
		}

		var touchList = createTouchList(mouseEv);
		if(isMultiTouch && mouseEv.type !== 'mouseup' && eventName === 'touchend') {
			touchList.splice(1, 1);
		}
		return touchList;
	}

	/**
	 * receive a filtered set of touches with only the changed pointers
	 * @param mouseEv
	 * @param eventName
	 * @returns {TouchList}
	 */
	function getChangedTouches(mouseEv, eventName) {
		var touchList = createTouchList(mouseEv);

		// we only want to return the added/removed item on multitouch
		// which is the second pointer, so remove the first pointer from the touchList
		//
		// but when the mouseEv.type is mouseup, we want to send all touches because then
		// no new input will be possible
		if(isMultiTouch && mouseEv.type !== 'mouseup' &&
			(eventName === 'touchstart' || eventName === 'touchend')) {
			touchList.splice(0, 1);
		}

		return touchList;
	}

	/**
	 * TouchEmulator initializer
	 */
	function TouchEmulator() {
		fakeTouchSupport();

		window.addEventListener("mousedown", onMouse('touchstart'), true);
		window.addEventListener("mouseup", onMouse('touchend'), true);

		// Move events disabled since they cause click issues
		// window.addEventListener("mousemove", onMouse('touchmove'), true);
	}

	// start distance when entering the multitouch mode
	TouchEmulator.multiTouchOffset = 75;

	TouchEmulator();
}).toString() + ")(window, document);";

document.documentElement.appendChild(s);